Cấu trúc các luật 78 

Một phần của tài liệu SQL injection - tấn công và cách phòng tránh (Trang 78 - 93)

2. Cấu hình 74 

2.2.Cấu trúc các luật 78 

Việc định nghĩa các luật là một công việc rất thường xuyên trong việc bảo trì, nâng cấp hệ thống WAF. Chỉ thị được sử dụng thường xuyên nhất để định nghĩa các luật đó là SecRule.

Để tự tạo, quản lý và bảo trì các luật phức tạp thế này không đơn giản. Trước tiên chúng ta sẽ tìm hiểu cấu trúc cú pháp của chỉ thị SecRule.

SecRule Target Operator [Actions]

ƒ Target: chỉđịnh thành phần nào đó của request hoặc response mà ta cần áp đặt luật. Target nhận giá trị là các biến, biến có thể là dạng biến thường và dạng biến tập, chúng ta sẽđề cập đến sau.

ƒ Operator: thành phần này chỉ định các phương thức, phép so sánh dữ

liệu được sử dụng khi thực hiện khớp với các biến cụ thể hoặc các biến. Operator mặc định, nếu không được chỉ định, là @rx, tức là rule engine sẽ sử dụng biểu thức chính quy để khớp xâu với biến cụ thể nào

đó.

ƒ Action: là một danh sách (tùy chọn) các hành động sẽ được áp đặt khi một luật được khớp (rule match). Những hành động này có thể là từ chối request và chỉđịnh mã lỗi trả về, …

Danh sách hành động này không bắt buộc, bởi nếu không được chỉ định, các hành động đã được khai báo mặc định trong chỉ thị

SecDefaultAction trong cấu hình cơ bản sẽđược áp đặt lên request.

2.2.1. Biến thường và các biến tập

ModSecurity sử dụng hai loại biến, loại thứ nhất là các biến chuẩn (standard variable) chỉ chứa một giá trịđơn ứng với mỗi biến, và loại thứ hai là các biến tập (collection variable) có thể chứa nhiều giá trị ứng với một biến. lấy một ví dụ về biến tập như REQUEST_HEADER, nó chứa tất cả giá trị trường header của một thông điệp HTTP.

Để truy cập vào các trường trong biến tập, sử dụng cấu trúc tên_biến:tên_trường, ví dụ luật sau:

SecRule REQUEST_HEADER:Referer “victim.com”

Hầu hết các biến tập có thể được sử dụng độc lập mà không cần chỉ định trường cụ thể. Khi sử dụng tên biến tập độc lập tương đương với việc truy cập tới mọi trường trong tập đó. Ví dụ, querystring gửi lên trong thông điệp POST như sau: username=cuongpt&password=weakpasswd. Thì thay vì sử dụng luật:

SecRule ARGS:username|ARGS:password “select”

Ta có thể sử dụng

SecRule ARGS “select” deny.

Một số biến tập có các trường cốđịnh (vd: GEO có country_name, city,…) nhưng một số lại có các trường không cố định, tùy thuộc vào nội dung client gửi đến.

Trong các biến tập, có thể truy cập tới các trường không tồn tại hoặc trường

đó không được gán giá trị mà không phát sinh lỗi. Điều này cần ghi nhớ trong trường hợp debug, có thể bỏ qua khả năng trường giá trị trong biến tập không tồn tại hoặc không được gán giá trị.

2.2.2. Lưu trữ dữ liệu giữa các request.

Có ba loại biến tập trong ModSecurity có thể được sử dụng để lưu trữ lâu dài. Thông thường, các biến sẽ hết hiệu lực mỗi khi request hiện thời được xử

lý hoàn tất. Tuy nhiên trong một số trường hợp, chúng ta lại cần lưu giữ chúng lại và sử dụng chúng khi thao tác với các request sau này. Ba loại biến tập có thểđược sử dụng cho mục đích lưu trữ là IP, SESSION, USER.

Biến tập IP được dùng để lưu thông tin về một user thông qua địa chỉ IP. Chúng ta có thể sử dụng nó cho một số mục đích như phát hiện ra user nào request nhiều lần vào một tài nguyên, hoặc số lần request của một user, giả sử để chống DOS.

Trước khi sử dụng các biến trên, chúng ta cần khởi tạo chúng cách sử dụng action tên là initcol, ví dụ:

SecAction initcol:ip=%{REMOTE_ADDR},nolog,pass

Trong đó, REMOTE_ADD là biến lưu địa chỉ IP của client gửi request. Để

lưu trữ biến, chúng ta cũng cần cấu hình một thư mục dữ liệu cho ModSecurity thông qua chỉ thị SecDataDir, ví dụ:

SecDataDir /var/log/apache2/modsec_data

Điều cần lưu ý đó là thư mục được chỉ định trong chỉ thị nêu trên phải cho phép người dùng Apache ghi dữ liệu lên.

Sau khi cấu hình thư mục lưu trữ dữ liệu, khởi tạo biến, ta có thể thao tác với giá trị của biến, gán giá trị thông qua action tên là setvar. Trong phần giới thiệu biến tập tiếp theo ta sẽ sử dụng action setvar.

2.2.3. Biến tập giao tác (transaction collection)

Biến TX là một dạng biến tập giao tác, các biến này được gán giá trị trong một vòng đời của một request/response. Chúng ta có thể sử dụng TX để tạo các biến của riêng mình nhằm lưu dữ liệu trong vòng một chu kỳ transaction. Xét một số luật sau:

SecRule REQUEST_URI “select” “pass,setvar:tx.score=+1” SecRule REQUEST_URI “passwd” “pass,setvar:tx.score=+2”

SecRule TX:SCORE “@gt 3” deny

Bộ luật trên mô tả như sau, thực hiện kiểm tra các URI trong request, nếu phát hiện có chứa “select” thì tăng biến SCORE lên 1, nếu phát hiện thấy có “passwd” thì tăng biến SCORE lên 2, và nếu kiểm tra thấy biến SCORE lớn hơn hoặc bằng 3 thì chặn request đó lại.

Cấu trúc action setvarở trên cho phép tạo và cập nhật một biến. Để hủy một biến, cũng sử dụng action setvar nhưng thêm dấu chấm than phía trước biến, cụ

thể: setvar:!tx.score.

Biến tập TX có thể chứa các trường định nghĩa sẵn (built-in) như TX:0, TX:1, … cho đến TX:9. Với trường hợp TX:0 đó là giá trị được khớp khi sử

dụng toán tử @rx hoặc @pm, các biến TX:1 đến TX:9 chứa các giá trị kiểu biểu thức chính quy thu được khi ước lượng một biểu thức chính quy kèm theo action capture.

2.2.4. Thực hiện thao tác đồng thời nhiều biến

Chúng ta có thể thực hiện so khớp một biểu thức chính quy với một vài biến một lúc, ví dụ cùng so khớp cả request header và request argument xem có xuất hiện “select” hay không thì cần dùng dấu | (pipe) để ngăn cách giữa các biến cần thực hiện so khớp, ví dụ:

SecRule ARGS|REQUEST_HEADERS “select” deny

2.2.5. Việc sử dụng các dấu nháy

Trong cấu trúc một luật, phần chuỗi action và biểu thức chính quy không nhất thiết phải luôn được bao bởi một cặp dấu nháy (như ví dụ ở trên). Nếu chuỗi action và biểu thức chính quy không chứa khoảng trắng (vd: dấu cách) bên trong thì không cần sử dụng dấu nháy để bọc chuỗi. Ngược lại, cần sử

dụng dấu nháy kép để bọc một chuỗi có chứa khoảng trắng bên trong. Ví dụ:

SecRule REQUEST_URI “waitfor delay” deny

Một trường hợp khác xảy ra, đó là dấu nháy xuất hiện với tư cách là thành phần hợp lệ của chuỗi, ví dụ với một thông báo trong log “someone’s try to hack us”, thì cần sử dụng dấu \ (backlash) để escape dấu đó, ví dụ ta có “someone\’s try to hack us”. Ngoài dấu nháy, các ký tự đặc biệt khác thường

gặp trong xử lý biểu thức chính quy cũng cần được escape, ví dụ dấu chấm, dấu sao, dấu mở ngoặc đơn, …

2.2.6. Xây dựng chuỗi các luật

Chuỗi các luật (chained rules) được sử dụng để kết hợp các luật lại sao cho một sự kiện khớp luật phải thỏa mãn điều kiện của một vài điều kiện thay vì chỉ

một điều kiện đơn lẻ.

Sử dụng action có tên là “chain” có thể cho phép ghép các luật lại thành một chuỗi xử lý. Một request/response khớp với chuỗi luật nếu khớp với tất cả

các luật thành viên. Từ khóa chain này có tác dụng tương tự phép thao tác logic AND trong các mệnh đề điều kiện ở các ngôn ngữ lập trình khác. Ví dụ với

điều kiện đặt ra như trên, ta có thể xây dựng chuỗi luật sau:

SecRule REQUEST_HEADERS:User-Agent “FlashGet” “deny,chain” SecRule TIME_HOUR “@lt 16”

Một điều cần chú ý, đó là chỉ có luật đầu tiên trong chuỗi mới có thể chỉ định các action có tính ngắt, ví dụ deny, nếu có luật nào khác luật đầu tiên chỉ định các action này, sẽ có lỗi xẩy ra. Ngoài deny, các metadata action khác như

log, msg, id, rev, tag, severity, logdata, cũng chỉ có thểđược chỉđịnh ở luật đầu tiên trong chuỗi.

Có thể ghép nhiều luật thành chuỗi chứ không chỉ hai luật như ví dụ. Khi đó chuỗi sẽ có đặc điểm sau:

™ Luật đầu tiên mô tả đầy đủ các hành động cần thiết để xử lý request/response khớp, kèm theo action “chain”

™ Các luật tiếp theo trừ luật cuối cùng, chỉ chứa duy nhất action là “chain”

™ Luật cuối cùng trong chuỗi, không chứa action nào

Các chuỗi luật phức tạp hơn chúng ta sẽ xây dựng, đề cập đến trong những nội dung mở rộng sau này.

2.2.7. Biểu thức chính quy

Biểu thức chính quy là một yếu tố căn bản được sử dụng để xây dựng nên các luật trong ModSecurity. Toán tử @rx (regular expression) là một toán tử

mặc định, được sử dụng khi không có một toán tử nào khác được chỉđịnh. Ngoài việc xây dựng trực tiếp mẫu so sánh hoàn toàn bằng biểu thức chính quy, có thể tận dụng một số toán tử hỗ trợđể giảm nhẹ công việc, ví dụ:

@beginsWith Khớp các chuỗi bắt đầu với chuỗi chỉđịnh SecRule REQUEST_LINE “!@beginsWith GET” @containts Khớp các chuỗi có chứa chuỗi chỉ định tại bất cứ vị trí nào SecRule REQUEST_LINE “@contains select”

@containsWord Khớp xâu chứa từđược chỉ định. “Từ” ở đây được hiểu là đoạn xâu được ngăn bởi một hoặc nhiều ký tự không phải chữ,số

SecRule ARGS “@containsWord from”

@endsWith Khớp xâu kết thúc bởi xâu chỉđịnh

SecRule ARGS “@endsWith --” @streq Khớp xâu giống hoàn toàn

xâu chỉđịnh SecRule REMOTE_HOST “@streq victim\.com” @within Khá giống @contains, chỉ khác là một so khớp xảy ra khi biến cần so xuất hiện bên trong xâu được chỉ định

SecRule REMOTE_USER “@within cuong,nam,an”

(sẽ khớp nếu remote user là cuong, nam hoặc an)

Các phép khớp xâu ở trên nhạy cảm kiểu chữ với xâu được chỉđịnh, cụ thể, kết quả sẽ khác với các xâu chỉđịnh là Select và seLect. Tuy nhiên, các toán tử

thì lại không phân biệt kiểu, tức là @within hay wiThin cũng vẫn hoạt động giống nhau.

Ngoài việc so khớp các chuỗi ký tự, chúng ta cũng cần đề cập đến việc sử

dụng các toán tửđể so sánh các số:

Toán tử Toán tử đại số tương đương

Ví dụ

@eq = SecRule RESPONSE_STATUS “@eq 200” @ge ≥ SecRule RESPONSE_STATUS “@ge 400” @gt > SecRule RESPONSE_STATUS “@gt 399” @le ≤ SecRule RESPONSE_STATUS “@le 199” @lt < SecRule RESPONSE_STATUS “@lt 200”

2.2.8. Một số các thao tác nâng cao với biến tập

™ Đếm số lượng đối tượng trong một biến tập

Chúng ta có thể thực hiện đếm số các đối tượng trong một biến tập bằng cách đặt dấu “&” vào trước biến tập đó. Giả sử chúng ta cần chặn các request mà không gửi cookie:

SecRule &REQUEST_COOKIE “@eq 0”

Ngoài ra có thể sử dụng đặc tính này để chặn một loại hình qua mặt WAF, đó là phương pháp có tên gọi “HTTP parameter pollution” đã được

đề cập ở chương . Phương pháp này sẽ tìm cách tách chuỗi giá trị tham số

thành nhiều cụm, lúc này sẽ xuất hiện ít nhất hai tham số có cùng tên, ví dụ

với URL:

http://site.com/search.php?keyword=select&keyword=version()--

có thể lập một luật để cản phương pháp này, ví dụ:

SecRule &ARGS:keyword “@ge 2”

™ Lọc các trường trong biến tập sử dụng biểu thức chính quy

Thay vì việc phải thao tác với tất cả các trường hoặc chỉđịnh đích danh một trường, ta có thể sử dụng biểu thức chính quy để thao tác với một số

trường có tên tương đồng nhau. Giả sử client submit một form đăng kí tài khoản, trong đó có các trường firstname, lastname, để ngăn ngừa nguy cơ

SQL Injection trong đó, ta có thể xây dựng một luật dạng như :

SecRule ARGS:/*name/ “select” deny

Luật trên sẽ chỉ bị vi phạm nếu một query string nào đó chứa tham số có tên chứa “name” và giá trị chứa “select”, nếu không vi phạm hai điều kiện này thì query string đó hợp lệ (đối với luật trên).

Cấu trúc tham chiếu đến trường trong biến tập sử dụng biểu thức chính quy có khác so với thông thường ở cặp dấu sổ chéo / (forward slash). Ta dùng cặp dấu này để thông báo cho engine luật rằng chuỗi bên trong cặp dấu đó là một biểu thức chính quy. Nếu không có cặp dấu sổ chéo ấy thì chỉ

những trường nào có tên đúng “*name” mới được tham chiếu.

™ Các hàm chuyển đổi

ModSecurity cung cấp một số các hàm chuyển đổi (transformation) có thể sử dụng cho các biến và biến tập. Các quá trình biến đổi dữ liệu được

thực hiện trên bản sao của dữ liệu cần thao tác, do đó các request/response ban đầu hoàn toàn không bị chỉnh sửa.

Để áp dụng một hàm chuyển đổi, chúng ta cần chỉđịnh tiền tố t: sau đó là tên hàm cần gọi, và đặt cụm này vào trong danh sách action của luật. Giả

sử muốn chuyển kiểu của tất cả các tham số trong querystring/POST sang dạng chữ thường trước khi tiến hành khớp với biểu thức chính quy thì có thể xây dựng luật như sau:

SecRule REQUEST_URI “<script” “deny,t:lowercase”

Luật trên sẽ chặn bất cứ URL nào chứa “<script”, không quan tâm tới xâu ký tựđó viết hoa hay thường thế nào.

Có rất nhiều các hàm chuyển đổi được cung cấp sẵn (tham khảo tại: (http://www.modsecurity.org/documentation/modsecurity-

apache/2.5.12/modsecurity2-apache-reference.html#transformation- functions).

Chúng ta liệt kê một số hàm cơ bản sau:

Tên hàm Tác dụng

compressWhitespace Chuyển các ký tự tab, xuống dòng, carriage return, form feed thành dấu cách, và chuyển nhiều dấu cách liên tiếp thành một dấu cách

htmlEntityDecode Giải mã các thuộc tính HTML đã mã hóa, ví dụ

chuyển &lt thành <

length Chuyển một chuỗi thành giá trịđộ dài của nó (kiểu số) lowercase Chuyển tất cả ký tự của chuỗi về dạng viết thường md5 Chuyển giá trịđầu vào thành mã băm md5 của nó none Xóa tất cả các hàm chuyển đổi đang thao tác trên luật

hiện thời

removeNull Xóa các byte null trong chuỗi

removeWhitespace Xóa tất cả các khoảng trắng trong chuỗi

replaceComments Thay tất cả các comment kiểu C (/* … */) bằng một ký tự dấu cách. Cụm ký tự mở khối comment /* cũng sẽ được thay bằng một dấu cách ngay cả khi thiếu ký tự */ tương ứng.

replaceNulls Thay các byte null bằng một dấu cách urlDecode Giải mã chuỗi có dạng mã hóa URL urlEncode Mã hóa chuỗi dạng URL

urlDecodeUni Tương tự urlDecode nhưng thao tác giải mã cả với những ký tựđược mã hóa Unicode dạng %uxxx sha1 Thay giá trịđầu vào bằng mã băm sha1 của nó trimLeft Xóa mọi khoảng trắng phía bên phía đầu xâu trimRight Xóa mọi khoảng trắng phía bên phía cuối xâu trim Xóa mọi khoảng trắng phía đầu và cuối xâu

2.2.9. Các toán tử nâng cao

Các nội dung trước chúng ta đã đề cập đến các toán tử thao tác dữ liệu như

biểu thức chính quy, so sánh chuỗi, so sánh số. Ngoài các toán tử trên còn có một số toán tử khác khá hữu ích trong những trường hợp cụ thể.

™ Khớp các mệnh đề với toán tử @pm và @pmFromFile

Chúng ta đã đề cập đến việc sử dụng biểu thức chính quy để khớp một trong các từ khác nhau với việc sử dụng toán tử | (pipe). Ví dụ khớp select hoặc update hoặc insert, ta có thể dùng biểu thức chính quy (select|insert|update). Ngoài ra, ModSecurity cũng cung cấp hai toán tử

khớp theo mệnh đề (phrase matching) có thể sử dụng để thay thế cho biểu thức chính quy như trên. Hai toán tửđó là @pm và pmFromFile.

Ta có hai luật sau, một sử dụng biểu thức chính quy, một sử dụng toán tử @pm, đều cho kết quả tương đương:

SecRule ARGS “select|insert|update” “deny,t:lowercase” SecRule ARGS “@pm select insert update” “deny,t:lowercase”

Các request gửi lên nếu chứa tham số chứa xâu “select”, ”insert”, ”update” (không phân biệt kiểu chữ hoa, thường) thì đều bị chặn.

Khi chúng ta có một danh sách dài các từ cần khớp, nếu liệt kê tất cả

chúng trong khai báo luật thì sẽ rất rối và bất tiện, ví dụ: “insert, xp_enumdsn, infile, openrowset, nvarchar, autonomous_transaction, print, data_type, or, outfile, inner, shutdown, tbcreator” hay thậm chí dài hơn như ở đoạn luật minh họa ban đầu. Để khắc phục điều này, ModSecurity cho

phép chúng ta khai báo các từ trên trong một file riêng và tham chiếu đến file đó với toán tử @pmFromFile.

Để thực hiện việc tham chiếu file trên, ta tạo một file, ví dụ

“/etc/modsecurity2/blacklist/keyword.txt”. Trong file trên ta nhập vào các từ cần khớp, mỗi từ một dòng. Khi đó luật sẽđược mô tả như sau:

SecRule ARGS “@pmFromFile /etc/modsecurity2/blacklist/keyword.txt” deny

Toán tử @pmFromFile sẽ đọc danh sách từ trong file keyword.txt nêu

Một phần của tài liệu SQL injection - tấn công và cách phòng tránh (Trang 78 - 93)